'use strict';

App.service('Page', ['$http', '$state', function($http, $state) { // injectables go here
	var self = this; // Save reference

	this.alert = function(message, okCallback) {
		layer.alert(message, function(index) {
			// do something
			if (okCallback) {
				okCallback();
			}
			layer.close(index);
		});
	};

	this.notice = function(message) {
		layer.msg(message);
	};

	this.confirm = function(message, okCallback, noCallback) {
		layer.confirm(message, {
			icon : 3,
			title : '提示'
		}, function(index) {
			if (okCallback) {
				okCallback();
			}
			layer.close(index);
		}, function(index) {
			if (noCallback) {
				noCallback();
			}
			layer.close(index);
		});
	};

	this.ajax = function(method, url, data, isFilter, callback, errorCallback) {
		// 加上时间戳，避免浏览器缓存
		url = url += (url.indexOf('?') > 0 ? '&' : '?') + '_t=' + (new Date()).valueOf();
		var loadi = null;
		if (isFilter) {
			loadi = layer.load(0);
		}
		$http({
			method : method,
			url : url,
			data : data,
			cache : false
		}).success(function(response) {
			if (loadi != null) {
				layer.close(loadi);
			}
			if (response.resultCode == '1' || url.indexOf('service/') == 0) { //成功
				if (callback) {
					callback(response);
				}
			} else if (errorCallback) {
				errorCallback(response)
			} else if (response.resultCode) {
				self.notice(response.resultDes);
			}
		}).error(function(response) {
			if (loadi != null) {
				layer.close(loadi);
			}
		});
	};

	this.ajaxPost = function(url, data, callback, errorCallback) {
		this.ajax('POST', url, data, true, callback, errorCallback);
	};

	this.ajaxPostQuiet = function(url, data, callback, errorCallback) {
		this.ajax('POST', url, data, false, callback, errorCallback);
	};

	this.ajaxGet = function(url, data, callback, errorCallback) {
		this.ajax('GET', url, data, true, callback, errorCallback);
	};

	this.ajaxGetQuiet = function(url, data, callback, errorCallback) {
		this.ajax('GET', url, data, false, callback, errorCallback);
	};

	this.ajaxPut = function(url, data, callback, errorCallback) {
		if (!data) {
			data = {};
		}
		data._method = 'PUT';
		this.ajaxPost(url, data, callback, errorCallback);
	},

	this.ajaxDelete = function(url, data, callback, errorCallback) {
		if (!data) {
			data = {};
		}
		data._method = 'DELETE';
		this.ajaxPost(url, data, callback, errorCallback);
	}

}]);

App.service('Form',[function() { // injectables go here

	this.toJson = function(formid, params) {
		if (!params) {
			params = {};
		}
		if (!formid) {
			return params;
		}
		var form = $(formid);
		var paramArray = form.serializeArray();
		$(paramArray).each(function() {
			params[this.name] = this.value;
		});

		// checkbox
		form.find("input[type='checkbox']").each(function() {
			var name = $(this).attr("name");
			params[name] = $(this).prop("checked") ? "1" : "0";
		});
		return params;
	};
	this.toJson2 = function(formid, params) {
		if (!params) {
			params = {};
		}
		if (!formid) {
			return params;
		}

		var form = $(formid);
		var paramArray = form.serializeArrayUnNull();
		$(paramArray).each(function() {
			if(params[this.name] !== undefined){
				if(!params[this.name].push){
					params[this.name] = [params[this.name]];
				}
				params[this.name].push(this.value || '');
			}else{
				params[this.name] = this.value || '';
			}
		});

		// checkbox
		form.find("input[type='checkbox']").each(function() {
			var name = $(this).attr("name");
			var value = $(this).prop("checked") ? "1" : "0";

			if(params[name] !== undefined){
				if(!params[name].push){
					params[name] = [params[name]];
				}
				params[name].push(value || '');
			}else{
				params[name] = value || '';
			}
		});
		return params;
	};

}]);

App.service('XCode',['$rootScope','Page', function($rootScope, Page) {

	// var options = {};

	this.init = function() {
		Page.ajaxPostQuiet('system/codes.do', null, function(response) {
			$rootScope.options = response.data;
		});
	}

	this.queryCodes = function(url, param, callback) {
		Page.ajaxPostQuiet(url, param, function(response) {
			var code = url;
			if (param) {
				code += angular.toJson(param);
			}
			$rootScope.options[code] = response.data;
			if (callback) {
				callback(response.data);
			}
		});
	}

	this.getName = function(codeType, value) {
		var name = value;
		$($rootScope.options[codeType]).each(function(index, option) {
			if (option.value == value) {
				name = option.name;
				return false;// break
			}
		});
		return name;
	};
	this.getSelectOption = function(codeType) {
		var options = $rootScope.options[codeType];
		if (!options) {
			options = [];
		}
		return options;
	}
}]);

App.service('Auth', ['$rootScope', function($rootScope) {

	this.validate = function(code) {
		var permission = $rootScope.user.permission[$rootScope.menuId || ''],
			permissionDeny = $rootScope.user.permissionDeny[$rootScope.menuId || ''];
		if (code && (permission || permissionDeny)) {
			if ((',' + permission + ',').indexOf(',' + code + ',') < 0
				&& (',' + permissionDeny + ',').indexOf(',' + code + ',') >= 0) {
				return false;
			}
		}
		return true;
	}

}]);

var Ztree = function () {

	return {

		// 取消选择
		unCheckAllNodes: function(dest) {
			dest.setting.view.expandSpeed = "";
			//dest.checkAllNodes(false);
			// 取消勾选的
			var checkedNodes = dest.getCheckedNodes(true), checkedLen = checkedNodes.length;
			if (checkedLen > 0) {
				for (var i = 0; i < checkedLen; i++) {
					dest.checkNode(checkedNodes[i], false);
				}
			}
			// 取消所有选择
			dest.cancelSelectedNode();

			dest.expandAll(false);
			dest.setting.view.expandSpeed = "fast";
		},

		// 选择节点
		checkNodes: function(dest, nodes, idKey) {
			$(nodes).each(function(index, node) {
				if (idKey) {
					node = dest.getNodeByParam(idKey, node[idKey], null);
				}
				if (node && !node.isParent) {
					dest.checkNode(node, true, true);
				}
			});
			// 展开所有选中节点
			var checkedNodes = dest.getCheckedNodes(true), checkedLen = checkedNodes.length;
			if (checkedLen > 0) {
				for (var i = 0; i < checkedLen; i++) {
					dest.expandNode(checkedNodes[i], true);
				}
			}
		},

		// 获取nodes2相对于nodes1减少的
		difference: function(nodes1, nodes2, idKey) {
			var ids = ',';
			$(nodes2).each(function(index, node) {
				ids += node[idKey] + ',';
			});
			var nodes = [];
			$(nodes1).each(function(index, node) {
				if (ids.indexOf(',' + node[idKey] + ',') < 0) {
					nodes.push(node);
				}
			});
			return nodes;
		},

		ids: function(nodes, idKey) {
			var ids = [];
			$(nodes).each(function(index, node) {
				ids.push(node[idKey]);
			});
			return ids;
		},

		search: function(tree, key, value, filter) {
			var nodes = tree.getNodesByParamFuzzy('highlight', '1');
			if(nodes && nodes.length > 0) {
				$(nodes).each(function (index, node) {
					node.highlight = '0';
					tree.updateNode(node);
				});
				// 展开根节点
				Ztree.expandRoot(tree);
			}
			if (value) {
				nodes = tree.getNodesByParamFuzzy(key, value);
				if(nodes && nodes.length > 0) {
					$(nodes).each(function(index, node) {
						if (!filter || filter(node)) {
							node.highlight = '1';
							tree.updateNode(node);
							Ztree.expandNode(tree, node, true);
						}
					});
				}
			}
		},

		expandNode: function(tree, node, expandFlag) {
			var parentNode = node.getParentNode();
			if (parentNode) {
				tree.expandNode(parentNode, expandFlag, false, false);
				return Ztree.expandNode(tree, parentNode, expandFlag);
			}
		},

		expandRoot: function(tree) {
			if (tree) {
				tree.setting.view.expandSpeed = "";
				tree.expandAll(false);
				// 根节点展开
				var roots = tree.getNodesByFilter(function (node) { return node.level == 0 });
				$(roots).each(function(index, node) {
					tree.expandNode(node, true, false, false);
				});
				tree.setting.view.expandSpeed = "fast";
			}
		},

		getRootParent: function(node) {
			var parentNode = node.getParentNode();
			if (parentNode) {
				return Ztree.getRootParent(parentNode);
			} else {
				return node;
			}
		},

		getData: function(item) {
			item = angular.copy(item);

			if (item) {
				delete item.children;
				delete item.tId;
				delete item.parentTId;
				delete item.open;
				//delete item.isParent;
				delete item.zAsync;
				delete item.isFirstNode;
				delete item.isLastNode;
				delete item.isAjaxing;
				delete item.checked;
				delete item.checkedOld;
				delete item.nocheck;
				delete item.chkDisabled;
				delete item.halfCheck;
				delete item.check_Child_State;
				delete item.check_Focus;

				delete item.getCheckStatus;
				delete item.getNextNode;
				delete item.getParentNode;
				delete item.getPreNode;
			}

			return item;
		}
	}

}();

var AppUtil = function () {

	return {

		// 获取model的小数点最后部分
		getModelName: function(modelName) {
			if (modelName.indexOf('.') > 0) {
				modelName = modelName.substring(modelName.lastIndexOf('.') + 1, modelName.length);
			}
			return modelName;
		},

		// 获取model的小数点最后部分
		getModelValue: function(scope, modelName) {
			if (modelName.indexOf('.') > 0) {
				var arr = modelName.split('.');
				var value = scope;
				$(arr).each(function(ii, modelName2) {
					if (angular.isUndefined(value)) {
						value = null;
						return false;
					} else {
						value = value[modelName2];
					}
				});
				return value;
			} else {
				return scope[modelName];
			}
		},

		jsonfy: function(json) {
			//return jsonfy('{' + (json || '') + '}');
			return eval('[{' + (json || '') + '}]')[0];
		},
		
		list_to_tree : function($list, $pk, $pid, $child, $root){
			$pk = $pk || 'id';
			$pid = $pid || 'pid';
			$child = $child || '_children';
			$root = $root || '0';
			var $tree = [];// 创建Tree
		    if($.isArray($list)) {
		        var $refer = [];
		        $($list).each(function(idx, data) {
		        	$refer[data[$pk]] = data;
		        });
		        
		        $($list).each(function(idx, data) {
		        	var pid = data[$pid];
		        	if($root == pid){
		        		$tree.push($refer[data[$pk]]);
		        	}else{
		        		if($refer[pid]){
		        			$refer[pid][$child] = $refer[pid][$child] || [];
		        			$refer[pid][$child].push($refer[data[$pk]]);
		        		}
		        	}
		        });
		    }
    		return $tree;
		},
		
		GPS : {
		    PI : 3.14159265358979324,
		    x_pi : 3.14159265358979324 * 3000.0 / 180.0,
		    delta : function (lat, lon) {
		        // Krasovsky 1940
		        //
		        // a = 6378245.0, 1/f = 298.3
		        // b = a * (1 - f)
		        // ee = (a^2 - b^2) / a^2;
		        var a = 6378245.0; //  a: 卫星椭球坐标投影到平面地图坐标系的投影因子。
		        var ee = 0.00669342162296594323; //  ee: 椭球的偏心率。
		        var dLat = this.transformLat(lon - 105.0, lat - 35.0);
		        var dLon = this.transformLon(lon - 105.0, lat - 35.0);
		        var radLat = lat / 180.0 * this.PI;
		        var magic = Math.sin(radLat);
		        magic = 1 - ee * magic * magic;
		        var sqrtMagic = Math.sqrt(magic);
		        dLat = (dLat * 180.0) / ((a * (1 - ee)) / (magic * sqrtMagic) * this.PI);
		        dLon = (dLon * 180.0) / (a / sqrtMagic * Math.cos(radLat) * this.PI);
		        return {'lat': dLat, 'lon': dLon};
		    },
		     
		    //WGS-84 to GCJ-02
		    gcj_encrypt : function (wgsLat, wgsLon) {
		        if (this.outOfChina(wgsLat, wgsLon))
		            return {'lat': wgsLat, 'lon': wgsLon};
		 
		        var d = this.delta(wgsLat, wgsLon);
		        return {'lat' : wgsLat + d.lat,'lon' : wgsLon + d.lon};
		    },
		    //GCJ-02 to WGS-84
		    gcj_decrypt : function (gcjLat, gcjLon) {
		        if (this.outOfChina(gcjLat, gcjLon))
		            return {'lat': gcjLat, 'lon': gcjLon};
		         
		        var d = this.delta(gcjLat, gcjLon);
		        return {'lat': gcjLat - d.lat, 'lon': gcjLon - d.lon};
		    },
		    //GCJ-02 to WGS-84 exactly
		    gcj_decrypt_exact : function (gcjLat, gcjLon) {
		        var initDelta = 0.01;
		        var threshold = 0.000000001;
		        var dLat = initDelta, dLon = initDelta;
		        var mLat = gcjLat - dLat, mLon = gcjLon - dLon;
		        var pLat = gcjLat + dLat, pLon = gcjLon + dLon;
		        var wgsLat, wgsLon, i = 0;
		        while (1) {
		            wgsLat = (mLat + pLat) / 2;
		            wgsLon = (mLon + pLon) / 2;
		            var tmp = this.gcj_encrypt(wgsLat, wgsLon)
		            dLat = tmp.lat - gcjLat;
		            dLon = tmp.lon - gcjLon;
		            if ((Math.abs(dLat) < threshold) && (Math.abs(dLon) < threshold))
		                break;
		 
		            if (dLat > 0) pLat = wgsLat; else mLat = wgsLat;
		            if (dLon > 0) pLon = wgsLon; else mLon = wgsLon;
		 
		            if (++i > 10000) break;
		        }
		        //console.log(i);
		        return {'lat': wgsLat, 'lon': wgsLon};
		    },
		    //GCJ-02 to BD-09
		    bd_encrypt : function (gcjLat, gcjLon) {
		        var x = gcjLon, y = gcjLat;  
		        var z = Math.sqrt(x * x + y * y) + 0.00002 * Math.sin(y * this.x_pi);  
		        var theta = Math.atan2(y, x) + 0.000003 * Math.cos(x * this.x_pi);  
		        var bdLon = z * Math.cos(theta) + 0.0065;
				var bdLat = z * Math.sin(theta) + 0.006;
		        return {'lat' : bdLat,'lon' : bdLon};
		    },
		    //BD-09 to GCJ-02
		    bd_decrypt : function (bdLat, bdLon) {
		        var x = bdLon - 0.0065, y = bdLat - 0.006;  
		        var z = Math.sqrt(x * x + y * y) - 0.00002 * Math.sin(y * this.x_pi);  
		        var theta = Math.atan2(y, x) - 0.000003 * Math.cos(x * this.x_pi);  
		        var gcjLon = z * Math.cos(theta);
		        var gcjLat = z * Math.sin(theta);
		        return {'lat' : gcjLat, 'lon' : gcjLon};
		    },
		    //WGS-84 to Web mercator
		    //mercatorLat -> y mercatorLon -> x
		    mercator_encrypt : function(wgsLat, wgsLon) {
		        var x = wgsLon * 20037508.34 / 180.;
		        var y = Math.log(Math.tan((90. + wgsLat) * this.PI / 360.)) / (this.PI / 180.);
		        y = y * 20037508.34 / 180.;
		        return {'lat' : y, 'lon' : x};
		        /*
		        if ((Math.abs(wgsLon) > 180 || Math.abs(wgsLat) > 90))
		            return null;
		        var x = 6378137.0 * wgsLon * 0.017453292519943295;
		        var a = wgsLat * 0.017453292519943295;
		        var y = 3189068.5 * Math.log((1.0 + Math.sin(a)) / (1.0 - Math.sin(a)));
		        return {'lat' : y, 'lon' : x};
		        //*/
		    },
		    // Web mercator to WGS-84
		    // mercatorLat -> y mercatorLon -> x
		    mercator_decrypt : function(mercatorLat, mercatorLon) {
		        var x = mercatorLon / 20037508.34 * 180.;
		        var y = mercatorLat / 20037508.34 * 180.;
		        y = 180 / this.PI * (2 * Math.atan(Math.exp(y * this.PI / 180.)) - this.PI / 2);
		        return {'lat' : y, 'lon' : x};
		        /*
		        if (Math.abs(mercatorLon) < 180 && Math.abs(mercatorLat) < 90)
		            return null;
		        if ((Math.abs(mercatorLon) > 20037508.3427892) || (Math.abs(mercatorLat) > 20037508.3427892))
		            return null;
		        var a = mercatorLon / 6378137.0 * 57.295779513082323;
		        var x = a - (Math.floor(((a + 180.0) / 360.0)) * 360.0);
		        var y = (1.5707963267948966 - (2.0 * Math.atan(Math.exp((-1.0 * mercatorLat) / 6378137.0)))) * 57.295779513082323;
		        return {'lat' : y, 'lon' : x};
		        //*/
		    },
		    // two point's distance
		    distance : function (latA, lonA, latB, lonB) {
		        var earthR = 6371000.;
		        var x = Math.cos(latA * this.PI / 180.) * Math.cos(latB * this.PI / 180.) * Math.cos((lonA - lonB) * this.PI / 180);
		        var y = Math.sin(latA * this.PI / 180.) * Math.sin(latB * this.PI / 180.);
		        var s = x + y;
		        if (s > 1) s = 1;
		        if (s < -1) s = -1;
		        var alpha = Math.acos(s);
		        var distance = alpha * earthR;
		        return distance;
		    },
		    outOfChina : function (lat, lon) {
		        if (lon < 72.004 || lon > 137.8347)
		            return true;
		        if (lat < 0.8293 || lat > 55.8271)
		            return true;
		        return false;
		    },
		    transformLat : function (x, y) {
		        var ret = -100.0 + 2.0 * x + 3.0 * y + 0.2 * y * y + 0.1 * x * y + 0.2 * Math.sqrt(Math.abs(x));
		        ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
		        ret += (20.0 * Math.sin(y * this.PI) + 40.0 * Math.sin(y / 3.0 * this.PI)) * 2.0 / 3.0;
		        ret += (160.0 * Math.sin(y / 12.0 * this.PI) + 320 * Math.sin(y * this.PI / 30.0)) * 2.0 / 3.0;
		        return ret;
		    },
		    transformLon : function (x, y) {
		        var ret = 300.0 + x + 2.0 * y + 0.1 * x * x + 0.1 * x * y + 0.1 * Math.sqrt(Math.abs(x));
		        ret += (20.0 * Math.sin(6.0 * x * this.PI) + 20.0 * Math.sin(2.0 * x * this.PI)) * 2.0 / 3.0;
		        ret += (20.0 * Math.sin(x * this.PI) + 40.0 * Math.sin(x / 3.0 * this.PI)) * 2.0 / 3.0;
		        ret += (150.0 * Math.sin(x / 12.0 * this.PI) + 300.0 * Math.sin(x / 30.0 * this.PI)) * 2.0 / 3.0;
		        return ret;
		    }
		}
	}

}();